<template>
  <div class="star-rating">
    <div class="stars-container">
      <div 
        v-for="(star, index) in stars" 
        :key="index"
        class="star"
        :class="{ 
          'filled': index < value,
          'hover': index < hoverValue,
          'animated': animated
        }"
        @click="handleStarClick(index + 1)"
        @mouseenter="hoverValue = index + 1"
        @mouseleave="hoverValue = 0"
      >
        <el-icon class="star-icon">
          <Star />
        </el-icon>
      </div>
    </div>
    
    <div v-if="showScore" class="score-display">
      <span class="score-text">{{ value }}.0</span>
      <span v-if="scoreText" class="score-description">{{ scoreText }}</span>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue'

/**
 * 带动画效果的星级评分组件
 * @description 提供悬停反馈和点击动画的星级评分功能
 * @param {number} modelValue - 当前评分值
 * @param {number} max - 最大星级数
 * @param {boolean} readonly - 是否只读
 * @param {boolean} showScore - 是否显示分数
 * @param {boolean} animated - 是否启用动画效果
 * @emits {number} update:modelValue - 评分变化时触发
 */
const props = defineProps({
  modelValue: {
    type: Number,
    default: 0
  },
  max: {
    type: Number,
    default: 5
  },
  readonly: {
    type: Boolean,
    default: false
  },
  showScore: {
    type: Boolean,
    default: true
  },
  animated: {
    type: Boolean,
    default: true
  }
})

const emit = defineEmits(['update:modelValue'])

const value = ref(props.modelValue)
const hoverValue = ref(0)

// 星级数组
const stars = computed(() => Array.from({ length: props.max }, (_, i) => i))

// 评分描述文本
const scoreText = computed(() => {
  const texts = {
    0: '暂无评分',
    1: '很差',
    2: '一般',
    3: '还行',
    4: '不错',
    5: '很棒'
  }
  return texts[value.value] || ''
})

/**
 * 处理星级点击事件
 * @param {number} starValue - 点击的星级值
 */
const handleStarClick = (starValue) => {
  if (props.readonly) return
  
  value.value = starValue
  emit('update:modelValue', starValue)
  
  // 添加点击动画效果
  if (props.animated) {
    const stars = document.querySelectorAll('.star.filled')
    stars.forEach((star, index) => {
      setTimeout(() => {
        star.style.transform = 'scale(1.2)'
        setTimeout(() => {
          star.style.transform = 'scale(1)'
        }, 150)
      }, index * 50)
    })
  }
}

// 监听外部值变化
watch(() => props.modelValue, (newValue) => {
  value.value = newValue
})
</script>

<style scoped>
.star-rating {
  display: flex;
  align-items: center;
  gap: 12px;
}

.stars-container {
  display: flex;
  gap: 4px;
}

.star {
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
}

.star-icon {
  font-size: 24px;
  color: #ddd;
  transition: all 0.3s ease;
}

.star.filled .star-icon {
  color: #ffd700;
  filter: drop-shadow(0 0 4px rgba(255, 215, 0, 0.5));
}

.star.hover .star-icon {
  color: #ffed4e;
  transform: scale(1.1);
}

.star.animated {
  animation: starPop 0.3s ease;
}

@keyframes starPop {
  0% { transform: scale(1); }
  50% { transform: scale(1.3); }
  100% { transform: scale(1); }
}

.score-display {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.score-text {
  font-size: 18px;
  font-weight: bold;
  color: #ffd700;
  text-shadow: 0 0 4px rgba(255, 215, 0, 0.3);
}

.score-description {
  font-size: 12px;
  color: #666;
  margin-top: 2px;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .star-icon {
    font-size: 20px;
  }
  
  .score-text {
    font-size: 16px;
  }
}
</style> 